package de.blitzcoder.collide.gui;

import de.blitzcoder.collide.icons.Icon;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ArrayList;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import org.noos.xing.mydoggy.AggregationPosition;
import org.noos.xing.mydoggy.Content;
import org.noos.xing.mydoggy.ContentManager;
import org.noos.xing.mydoggy.ContentManagerUIListener;
import org.noos.xing.mydoggy.MultiSplitConstraint;
import org.noos.xing.mydoggy.MultiSplitContentManagerUI;
import org.noos.xing.mydoggy.TabbedContentManagerUI.TabLayout;
import org.noos.xing.mydoggy.event.ContentManagerUIEvent;
import org.noos.xing.mydoggy.plaf.ui.content.MyDoggyMultiSplitContentManagerUI;

/**
 *
 * @author blitzcoder
 */
public class DockingDocumentManager extends DocumentManager implements ContentManagerUIListener, ActionListener {

    // The ToolWindowManager
    private ContentManager manager;
    
    // The Documents
    private ArrayList<Content> content;
    private ArrayList<Document> documents;

    // ID count
    private int id = 0;

    public DockingDocumentManager(ContentManager manager) {
        this.manager = manager;
        content = new ArrayList<Content>();
        documents = new ArrayList<Document>();
        
        MultiSplitContentManagerUI managerUI = new MyDoggyMultiSplitContentManagerUI();
        manager.setContentManagerUI(managerUI);

        managerUI.setTabLayout(TabLayout.SCROLL);
        managerUI.setShowAlwaysTab(true);
        managerUI.addContentManagerUIListener(this);
        managerUI.setMinimizable(false);

    }

    @Override
    public void bringToFront(Document doc) {
        getContentForDocument(doc).setSelected(true);
    }

    private Content getContentForDocument(Document doc) {
        return content.get(documents.indexOf(doc));
    }
    
    private Document getDocumentForContent(Content con) {
        int index = content.indexOf(con);
        if (index == -1)
            return null;
        return documents.get(index);
    }

    @Override
    public boolean removeDocument(Document doc) {
        if (doc.close()) {
            Content c = getContentForDocument(doc);
            manager.removeContent(c);
            content.remove(c);
            documents.remove(doc);
            fireDocumentRemoved(doc);
            return true;
        }
        return false;
    }

    @Override
    public Document getCurrentDocument() {
        Content c = manager.getSelectedContent();
        return c == null ? null : getDocumentForContent(c);
    }

    @Override
    public int getCurrentDocumentIndex() {
        Document doc = getCurrentDocument();
        return doc == null ? null : documents.indexOf(doc);
    }

    @Override
    public Document[] getAllDocuments() {
        return documents.toArray(new Document[0]);
    }

    @Override
    public void finishDocumentInsertion(final Document doc) {
        
        final Content c = getContentForDocument(doc);

        JPopupMenu menu = new JPopupMenu();
        JMenuItem closeAll = new JMenuItem("Alle Dokumente schließen");
        JMenuItem closeOther = new JMenuItem("Alle anderen Dokumente schließen");
        JMenuItem close = new JMenuItem("Schließen");
        JMenuItem clone = new JMenuItem("Klonen");

        closeAll.setIcon(Icon.load("closetab_mouseover.png"));
        closeOther.setIcon(Icon.load("closetab_mouseover.png"));
        close.setIcon(Icon.load("closetab_mouseover.png"));

        closeAll.setActionCommand("CloseAll");
        closeAll.addActionListener(this);

        clone.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                addDocument(doc.cloneDocument());
            }
        });

        closeOther.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removeOtherDocuments(doc);
            }
        });

        close.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                removeDocument(doc);
            }
        });

        doc.addUpdateListener(new Document.UpdateListener() {
            public void update(Document doc) {
                c.setTitle(doc.getTitle());
                c.setToolTipText(doc.getToolTipText());
                c.setIcon(doc.getIcon());
            }
        });

        menu.add(closeAll);
        menu.add(closeOther);
        menu.addSeparator();
        if (doc.isClonable())
            menu.add(clone);
        menu.add(close);

        c.setPopupMenu(menu);

        c.getContentUI().setMinimizable(true);

        doc.documentInserted(c.getPopupMenu());

        c.setTitle(doc.getTitle());
        c.setToolTipText(doc.getToolTipText());
        c.setIcon(doc.getIcon());

        JPanel panel = (JPanel) c.getComponent();
        panel.removeAll();
        panel.add(doc);

        fireDocumentAdded(doc);

        c.setSelected(true);
        fireDocumentSelected(doc);

        addFocusListenerToComponentTree(doc, new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                fireDocumentSelected(doc);
            }
            @Override
            public void focusLost(FocusEvent e) {}
        });

    }

    /*
     * Es ist möglich, dass dieser DocumentManager aus mehreren JTabbedPanes besteht, deren selectedIndex
     * sich nicht ändert, wenn man ein Dokument auswählt. Das documentSelected Event wird daher aufgerufen,
     * wenn eine Komponente im Document den Fokus bekommt.
     */
    private void addFocusListenerToComponentTree(JComponent comp, FocusListener lis) {
        comp.addFocusListener(lis);
        Component[] comps = comp.getComponents();
        for (Component c:comps) {
            if (c instanceof JComponent)
                addFocusListenerToComponentTree((JComponent) c, lis);
            else
                c.addFocusListener(lis);
        }
    }

    @Override
    public synchronized void startDocumentInsertion(Document doc) {

        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout());
        panel.add(new JLabel("Loading..."));

        MultiSplitConstraint constraint;
        int size = content.size();
        if (size != 0)
            constraint = new MultiSplitConstraint(content.get(0));
        else
            constraint = new MultiSplitConstraint(AggregationPosition.BOTTOM);

        Content c = manager.addContent(id+"", "Loading...", null, panel,null,constraint);
        
        documents.add(doc);
        content.add(c);

        id++;

        c.setSelected(true);

    }

    @Override
    public JComponent getComponent() {
        throw new RuntimeException("No Component needed for this DocumentManager");
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("CloseAll"))
            removeAllDocuments();
    }

    @Override
    public boolean contentUIRemoving(ContentManagerUIEvent e) {
        if (getCurrentDocument().close()) {
            Content c = e.getContentUI().getContent();
            documents.remove(getDocumentForContent(c));
            content.remove(c);
            return true;
        }
        return false;
    }

    // Unused
    public void contentUIDetached(ContentManagerUIEvent arg0) {}

}
